package business.aluguel;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import business.sistema.ObjetoSistema;

public class Aluguel extends ObjetoSistema
{
	private static final long serialVersionUID = -8263389506023864587L;
	private int codigo;
	private Date dataSaida;
	private Date dataDevolucaoPrevista;
	private Date dataDevolucaoReal;
	private double valorMotoristaExtra = 0.0;
	private double valorDiaria;
	private double valorFranquia;
	private Cliente cliente;
	private Set<MotoristaAdicional> motoristas;
	private Set<Custo> custos;
	private Veiculo veiculo;
	private PosicaoAluguel posicaoAluguel;
	private double total;
	private int diarias;
	private double horasExtras;
	private double valorHoraExtra;
	private String formaPagamento;
	private String observacao;
	
	public int getCodigo()
	{
		return codigo;
	}
	
	public void setCodigo(int codigo)
	{
		this.codigo = codigo;
	}
	
	public Date getDataSaida()
	{
		return dataSaida;
	}
	
	public void setDataSaida(Date dataSaida)
	{
		this.dataSaida = dataSaida;
	}
	
	public Date getDataDevolucaoPrevista()
	{
		return dataDevolucaoPrevista;
	}
	
	public void setDataDevolucaoPrevista(Date dataDevolucaoPrevista)
	{
		this.dataDevolucaoPrevista = dataDevolucaoPrevista;
	}
	
	public void setDataDevolucaoReal(Date dataDevolucaoReal)
	{
		this.dataDevolucaoReal = dataDevolucaoReal;
	}

	public Date getDataDevolucaoReal()
	{
		return dataDevolucaoReal;
	}

	public void setValorMotoristaExtra(double valorMotoristaExtra)
	{
		this.valorMotoristaExtra = valorMotoristaExtra;
	}

	public double getValorMotoristaExtra()
	{
		return valorMotoristaExtra;
	}
	
	public double getValorTotalMotoristaExtra()
	{
		double total = 0.0;
		
		if(motoristas != null)
		{
			total = (motoristas.size() * valorMotoristaExtra);
		}
		
		return total; 
	}

	public void setValorDiaria(double valorDiaria)
	{
		this.valorDiaria = valorDiaria;
	}

	public double getValorDiaria()
	{
		return valorDiaria;
	}

	public void setValorFranquia(double valorFranquia)
	{
		this.valorFranquia = valorFranquia;
	}

	public double getValorFranquia()
	{
		return valorFranquia;
	}

	public Cliente getCliente()
	{
		return cliente;
	}
	
	public void setCliente(Cliente cliente)
	{
		this.cliente = cliente;
	}
	
	public String getNomeCliente()
	{
		return getCliente().getNome();
	}
	
	public Set<MotoristaAdicional> getMotoristas()
	{
		return motoristas;
	}
	
	public void setMotoristas(Set<MotoristaAdicional> motoristas)
	{
		this.motoristas = motoristas;
	}
	
	public boolean addMotorista(Cliente motorista)
	{
		boolean jaCadastrado = false;
		
		if(motoristas == null)
		{
			motoristas = new HashSet<MotoristaAdicional>();
		}
		
		for(MotoristaAdicional motoristaAluguelCadastrado : motoristas)
		{
			if(motorista.getCnh().equals(motoristaAluguelCadastrado.getCnh()))
			{
				jaCadastrado = true;
				break;
			}
		}
		
		if(!jaCadastrado)
		{
			MotoristaAdicional motoristaAluguel = new MotoristaAdicional();
			
			motoristaAluguel.setCliente(motorista);
			motoristaAluguel.setAluguel(this);
			motorista.setMotoristaAdicional(motoristaAluguel);
			
			motoristas.add(motoristaAluguel);
		}
		
		return jaCadastrado;
	}
	
	public void removeMotorista(MotoristaAdicional motorista) 
	{
		motoristas.remove(motorista);
	}
	
	public Set<Custo> getCustos()
	{
		return custos;
	}
	
	public void setCustos(Set<Custo> custos)
	{
		this.custos = custos;
	}
	
	public boolean addCusto(Custo custo)
	{
		boolean jaCadastrado = false;
		
		if(custos == null)
		{
			custos = new HashSet<Custo>();
		}
		
		for(Custo custoCadastrado : custos)
		{
			if(custo.getProduto().getCodigo() == custoCadastrado.getProduto().getCodigo())
			{
				jaCadastrado = true;
				break;
			}
		}
		
		if(!jaCadastrado)
		{
			custos.add(custo);
			custo.setAluguel(this);
		}
		
		return jaCadastrado;
	}
	
	public void removerCusto(Custo custo)
	{
		custos.remove(custo);
	}
	
	public Veiculo getVeiculo()
	{
		return veiculo;
	}
	
	public void setVeiculo(Veiculo veiculo)
	{
		this.veiculo = veiculo;
	}
	
	public void setPosicaoAluguel(PosicaoAluguel posicaoAluguel)
	{
		this.posicaoAluguel = posicaoAluguel;
	}

	public PosicaoAluguel getPosicaoAluguel()
	{
		return posicaoAluguel;
	}
	
	public String getNomePosicaoAluguel()
	{
		return getPosicaoAluguel().getNome();
	}
	
	public double calcular()
	{
		double valorTotal = 0.0;
		
		// Calcula a quantidade de diárias.
		if(getPosicaoAluguel().getCodigo() == PosicaoAluguel.CODIGO_ABERTO)
		{
			double dias = diferencaEmDias(getDataSaida(), dataDevolucaoPrevista);
			diarias = (int)dias;
			horasExtras = (dias - diarias) * 24;
			double valorDiaria = getValorDiaria();
			valorHoraExtra = 0.0;
			
			if(horasExtras < 3)
			{
				valorHoraExtra = 0.0;
			}
			else
			if(horasExtras < 4)
			{
				valorHoraExtra = valorDiaria * 1/5;
			}
			else
			if(horasExtras < 5)
			{
				valorHoraExtra = valorDiaria * 2/5;
			}
			else
			if(horasExtras < 6)
			{
				valorHoraExtra = valorDiaria * 3/5;
			}
			else
			if(horasExtras < 7)
			{
				valorHoraExtra = valorDiaria * 4/5;
			}
			else
			{
				diarias++;
				horasExtras = 0.0;
			}
			
			valorTotal += (valorDiaria * diarias) + valorHoraExtra;
		}
		else
		if(getPosicaoAluguel().getCodigo() == PosicaoAluguel.CODIGO_FECHADO)
		{
			double dias = diferencaEmDias(getDataSaida(), dataDevolucaoReal);
			diarias = (int)dias;
			horasExtras = (dias - diarias) * 24;
			double valorDiaria = getValorDiaria();
			valorHoraExtra = 0.0;
			
			if(horasExtras < 3)
			{
				valorHoraExtra = 0.0;
			}
			else
			if(horasExtras < 4)
			{
				valorHoraExtra = valorDiaria * 1/5;
			}
			else
			if(horasExtras < 5)
			{
				valorHoraExtra = valorDiaria * 2/5;
			}
			else
			if(horasExtras < 6)
			{
				valorHoraExtra = valorDiaria * 3/5;
			}
			else
			if(horasExtras < 7)
			{
				valorHoraExtra = valorDiaria * 4/5;
			}
			else
			{
				diarias++;
				horasExtras = 0.0;
			}
			
			valorTotal += (valorDiaria * diarias) + valorHoraExtra;
		}
		
		// Calcula a quantidade de motoristas adicionais
		valorTotal += getValorTotalMotoristaExtra();
		
		// Recupera o custos adicionais.
		if(custos != null)
		{
			for(Custo custo : getCustos())
			{
				valorTotal += custo.getCustoTotal();
			}
		}
		
		return valorTotal;
	}
	
	public double getTotal()
	{
		total = calcular();
		
		return total;
	}
	
	public void setTotal(double total)
	{
		this.total = total;
	}
	
	public void setDiarias(int diarias)
	{
		this.diarias = diarias;
	}

	public int getDiarias()
	{
		return diarias;
	}
	
	public double getHorasExtras()
	{
		return horasExtras;
	}

	public void setHorasExtras(double horasExtras)
	{
		this.horasExtras = horasExtras;
	}

	public void setValorHoraExtra(double valorHoraExtra)
	{
		this.valorHoraExtra = valorHoraExtra;
	}

	public double getValorHoraExtra()
	{
		return valorHoraExtra;
	}

	public double getValorTotalDiarias()
	{
		return getValorDiaria() * getDiarias();
	}

	private double diferencaEmDias(Date dataInicial, Date dataFinal)
	{
		long m1 = dataInicial.getTime();
		long m2 = dataFinal.getTime();
		return (m2 - m1) / ((double)(24*60*60*1000));
	}
	
	public void finalizar()
	{
		if(getPosicaoAluguel().getCodigo() == PosicaoAluguel.CODIGO_FECHADO)
		{
			setPosicaoAluguel(PosicaoAluguel.ABERTO());
			setDataDevolucaoReal(null);
		}
		else
		{		
			setPosicaoAluguel(PosicaoAluguel.FECHADO());
			setDataDevolucaoReal(new Date());
		}
	}
	
	public Date getDataDevolucao()
	{
		Date devolucao = null;
		
		if(getPosicaoAluguel().getCodigo() == PosicaoAluguel.CODIGO_ABERTO)
		{
			devolucao = getDataDevolucaoPrevista();
		}
		else
		{
			devolucao = getDataDevolucaoReal();
		}
		
		return devolucao;
	}

	public void setFormaPagamento(String formaPagamento)
	{
		this.formaPagamento = formaPagamento;
	}

	public String getFormaPagamento()
	{
		return formaPagamento;
	}

	public String getObservacao()
	{
		return observacao;
	}

	public void setObservacao(String observacao)
	{
		this.observacao = observacao;
	}
}
